/*
 * InvulgoTracker
 * Copyright (C) Thomas Andersen 2011 <thomas.1.andersen@gmail.com>
 * 
 * InvulgoTracker is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * InvulgoTracker is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#include <config.h>

#include "gettextmacro.h"
#include "task-view.h"
#include "detail-view.h"
#include "day.h"
#include "invulgotrackerapp.h"


DetailView::DetailView()
{
}


DetailView::~DetailView()
{
    g_object_unref (model);
    gtk_tree_view_set_model (view, NULL);
    while (gtk_tree_view_remove_column(view, gtk_tree_view_get_column(view, 0)) > 0);
}

GtkTreeModel *DetailView::CreateModel()
{
    GtkListStore  *store;

    store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);

    return GTK_TREE_MODEL (store);
}


extern "C" gint DetailView::sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter  *a, GtkTreeIter  *b, gpointer userdata)
{
    gint sortcol = GPOINTER_TO_INT(userdata);
    gint ret = 0;

    gchar *name1, *name2;

    gtk_tree_model_get(model, a, sortcol, &name1, -1);
    gtk_tree_model_get(model, b, sortcol, &name2, -1);

    if (name1 == NULL || name2 == NULL)
    {
        if (name1 == NULL && name2 == NULL)
            ;
        else
            ret = (name1 == NULL) ? -1 : 1;
    }
    else
    {
        ret = g_utf8_collate(name1,name2);
    }

    g_free(name1);
    g_free(name2);

    return ret;
}


extern "C" void DetailView::column_date_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    DetailView *sv = (DetailView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_DATE);
}

extern "C" void DetailView::column_title_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    DetailView *sv = (DetailView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_TITLE);
}

void DetailView::ColumnClicked(GtkTreeViewColumn *treeViewColumn, gint columnSortId)
{
    GtkTreeSortable *sortable;
    GtkSortType      order;
    gint             sortid;

    sortable = GTK_TREE_SORTABLE(model);

    /* If we are already sorting by year, reverse sort order,
     *  otherwise set it to year in ascending order */
    g_object_set(treeViewColumn, "sort-indicator", TRUE ,NULL);
    if (gtk_tree_sortable_get_sort_column_id(sortable, &sortid, &order) == TRUE &&  sortid == columnSortId) {
        GtkSortType neworder;
        neworder = (order == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
        gtk_tree_sortable_set_sort_column_id(sortable, columnSortId, neworder);
        g_object_set(treeViewColumn, "sort-order", neworder ,NULL);
    } else {
        GList *list = gtk_tree_view_get_columns(view);
        do {
            if (list && list->data != treeViewColumn)
                g_object_set(list->data, "sort-indicator", FALSE ,NULL);
        } while((list = g_list_next(list)));
        g_list_free(list);
        gtk_tree_sortable_set_sort_column_id(sortable, columnSortId, GTK_SORT_ASCENDING);
        g_object_set(treeViewColumn, "sort-order", GTK_SORT_ASCENDING ,NULL);
    }
}


extern "C" void DetailView::column_duration_clicked(GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
{
    DetailView *sv = (DetailView*)user_data;
    sv->ColumnClicked(treeviewcolumn, SORT_DURATION);
}

void DetailView::Init(GtkWidget *view, gboolean sortable)
{
    GtkCellRenderer *renderer;

    this->view = GTK_TREE_VIEW(view);

    model = CreateModel();

    /* Date */
    renderer = gtk_cell_renderer_text_new ();
    GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_("Date"),  renderer, "text", COL_DATE, NULL);
    if (sortable) {
        g_object_set(column, "reorderable", TRUE ,NULL);
        g_object_set(column, "clickable", TRUE ,NULL);
        g_object_set(column, "sort-indicator", TRUE ,NULL);
        g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_date_clicked), this);
    }
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    /* Item */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes(_("Item"),  renderer, "text", COL_TITLE, NULL);
    //    gtk_tree_view_column_set_resizable(column, TRUE);
    g_object_set(column, "sizing",GTK_TREE_VIEW_COLUMN_AUTOSIZE,NULL);
    if (sortable) {
        g_object_set(column, "reorderable", TRUE ,NULL);
        g_object_set(column, "clickable", TRUE ,NULL);
        g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_title_clicked), this);
    }
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    /* Duration */
    renderer = gtk_cell_renderer_text_new ();
    g_object_set(renderer, "xalign",1.0,NULL);
    column = gtk_tree_view_column_new_with_attributes(_("Duration"),  renderer, "text", COL_DURATION, NULL);
    if (sortable) {
        g_object_set(column, "reorderable", TRUE ,NULL);
        g_object_set(column, "clickable", TRUE ,NULL);
        g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(column_duration_clicked), this);
    }
    gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, -1);

    if (sortable) {
        GtkTreeSortable *sortable = GTK_TREE_SORTABLE(model);
        gtk_tree_sortable_set_sort_func(sortable, SORT_DATE, sort_iter_compare_func,GINT_TO_POINTER(SORT_DATE), NULL);
        gtk_tree_sortable_set_sort_func(sortable, SORT_TITLE, sort_iter_compare_func,GINT_TO_POINTER(SORT_TITLE), NULL);
        gtk_tree_sortable_set_sort_func(sortable, SORT_DURATION, sort_iter_compare_func,GINT_TO_POINTER(SORT_DURATION), NULL);
        /* set initial sort order */
        gtk_tree_sortable_set_sort_column_id(sortable, SORT_DATE, GTK_SORT_ASCENDING);
    }
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);

}

void DetailView::CalcDay(guint year, guint month, guint day, gboolean accumulate)
{
    this->year = year;
    this->month = month;
    this->day = day;
    Day dayloader(year, month, day);

    prevTime = NULL;
    dayloader.Load(this);
    if (prevTime)
        delete prevTime;

}


void DetailView::Data(gchar *name, gchar *timeStr, TaskId id)
{
    TaskTime taskTime(timeStr);
    free(timeStr);
    AddTask(name, id, taskTime);
}


void DetailView::AddTask(gchar *taskName, TaskId id, TaskTime tt)
{
    GtkTreeIter iter;

    /* Calc previous duration. */
    if (prevTime) {
        gchar *durationText = NULL;
        TaskTime diff = tt.SubTime(*prevTime);
        delete prevTime;
        durationText = diff.TimeText();
        gtk_list_store_set (GTK_LIST_STORE(model), &prevIter,
                            COL_DURATION, durationText?durationText:"",
                            -1);
        free(durationText);
    }

    /* Add new entry */
    TaskTime date(year, month+1, day);
    char *timeText = tt.TimeText();
    char *dateText = date.DateText();
    char *dateStr = new char[strlen(dateText)+1+strlen(timeText)+1];
    strcpy(dateStr,dateText);
    strcat(dateStr,".");
    strcat(dateStr,timeText);
    gtk_list_store_append (GTK_LIST_STORE(model), &iter);
    gtk_list_store_set (GTK_LIST_STORE(model), &iter,
                        COL_DATE, dateStr,
                        COL_TITLE, taskName,
                        COL_ID, (const gchar *)id,
                        -1);
    /* Save previous. */
    prevTime = new TaskTime(tt);
    prevIter = iter;
    /* Clean */
    g_free(taskName);
    free(timeText);
    free(dateText);
    free(dateStr);

}


bool DetailView::GetFirst(gchar **dateStr, gchar **name, gchar **durationStr)
{
    if (gtk_tree_model_get_iter_first(model, &currentIter)) {
        gtk_tree_model_get(model, &currentIter,
                           COL_DATE, dateStr,
                           COL_TITLE, name,
                           COL_DURATION, durationStr,
                           -1);
        return true;
    }
    return false;
}

bool DetailView::GetNext(gchar **dateStr, gchar **name, gchar **durationStr)
{
    if (gtk_tree_model_iter_next(model, &currentIter)) {
        gtk_tree_model_get(model, &currentIter,
                           COL_DATE, dateStr,
                           COL_TITLE, name,
                           COL_DURATION, durationStr,
                           -1);
        return true;
    }
    return false;
}




